package com.lagou.filter;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class RemoteCallStatics implements Runnable {
    private ReentrantLock lock;

    private Map<String, List<Long>> statics;
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss");

    private static int coreSize = Runtime.getRuntime().availableProcessors();
    private static ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(coreSize);

    public RemoteCallStatics() {
        lock = new ReentrantLock();
        this.statics = new HashMap<>();

        scheduledPool.scheduleWithFixedDelay(this, 5,
                5, TimeUnit.SECONDS);
    }

    //添加调用统计信息
    public void collect(String methodName, Long elapse) {
        lock.lock();

        try {
            if (this.statics.get(methodName) == null) {
                List<Long> staticsList = new ArrayList<>();
                staticsList.add(elapse);
                statics.put(methodName, staticsList);
            }
            else {
                List<Long> staticsList = statics.get(methodName);
                staticsList.add(elapse);
            }
        }
        finally {
            lock.unlock();
        }

    }

    //每隔一定时间进行统计
    @Override
    public void run() {
        Map<String,List<Long>> copied = copyStatics();
        Map<String, Long> tp90 = new HashMap<>();
        Map<String, Long> tp99 = new HashMap<>();

        for (Map.Entry<String, List<Long>> entry: copied.entrySet()) {
            String methodName = entry.getKey();
            List<Long> list = entry.getValue();
            if (list.size() > 0) {
                list.sort((a, b) -> {return Long.compare(a, b);});

                int tp90Index = (int) Math.ceil(list.size() * 0.9 - 1);
                tp90.put(methodName, list.get(tp90Index));

                int tp99Index = (int) Math.ceil(list.size() * 0.99 - 1);
                tp99.put(methodName, list.get(tp99Index));
            }
        }

        System.out.println("==========统计时间(" + sdf.format(new Date()) +  ")==========");
        printStatics("tp90", tp90);
        printStatics("tp99", tp99);
        System.out.println();
    }

    private Map<String, List<Long>> copyStatics() {
        Map<String, List<Long>> copied = new HashMap<>();

        lock.lock();
        try {
            for (Map.Entry<String, List<Long>> entry : this.statics.entrySet()) {
                String methodName = entry.getKey();
                List<Long> statics = entry.getValue();
                List<Long> copyList = new ArrayList<>();
                copyList.addAll(statics);
                copied.put(methodName, copyList);
            }
        }
        finally {
            lock.unlock();
        }

        return copied;
    }

    //打印统计结果
    private void printStatics(String metricsName, Map<String, Long> statics) {
        System.out.println("==========" + metricsName + "==========");
        for (Map.Entry<String, Long> entry : statics.entrySet()) {
            System.out.println(entry.getKey() + "===>" +entry.getValue());
        }
    }
}
